package cc.rengu.igas.bsps.core.service.trans;

import cc.rengu.igas.bsps.common.constant.BspsAppParamConstant;
import cc.rengu.igas.bsps.common.constant.DubboMethodConstant;
import cc.rengu.igas.bsps.common.dao.*;
import cc.rengu.igas.bsps.common.dao.impl.*;
import cc.rengu.igas.bsps.common.entity.*;
import cc.rengu.igas.bsps.common.enums.BspsMchntTypeEnum;
import cc.rengu.igas.bsps.common.enums.BspsUserRoleTypeEnum;
import cc.rengu.igas.bsps.common.enums.MchntStatusEnum;
import cc.rengu.igas.bsps.common.enums.RespCodeEnum;
import cc.rengu.igas.bsps.core.model.UserSessionInfo;
import cc.rengu.igas.bsps.core.service.base.ManageService;
import cc.rengu.igas.bsps.facade.request.MchntBindAuthRequest;
import cc.rengu.igas.bsps.facade.response.MchntBindAuthResponse;
import cc.rengu.igas.share.common.util.GlobalEsbUtil;
import cc.rengu.igas.share.common.util.SensitiveDataUtil;
import cc.rengu.igas.share.core.model.GroupMchntInfo;
import cc.rengu.igas.share.core.realize.MchntService;
import cc.rengu.igas.share.core.realize.impl.MchntServiceImpl;
import cc.rengu.igas.smps.facade.base.Header;
import cc.rengu.igas.smps.facade.request.GeneralSmsNoticeRequest;
import cc.rengu.igas.smps.facade.response.GeneralSmsNoticeResponse;
import cc.rengu.igas.smps.facade.result.Result;
import cc.rengu.oltp.service.common.constant.AppParamConstant;
import cc.rengu.oltp.service.common.dao.MsgTemplateCfgMapper;
import cc.rengu.oltp.service.common.dao.impl.MsgTemplateCfgMapperImpl;
import cc.rengu.oltp.service.common.entity.ChannelCallCfg;
import cc.rengu.oltp.service.common.entity.MsgTemplateCfg;
import cc.rengu.oltp.service.common.entity.SmsInfo;
import cc.rengu.oltp.service.common.enums.ChannelEnum;
import cc.rengu.oltp.service.common.enums.SmsTypeEnum;
import cc.rengu.oltp.service.common.enums.TemplateTypeEnum;
import cc.rengu.oltp.service.model.BizException;
import cc.rengu.oltp.service.model.BizResponse;
import cc.rengu.oltp.service.realize.DubboService;
import cc.rengu.oltp.service.realize.SmsService;
import cc.rengu.oltp.service.realize.impl.DubboServiceImpl;
import cc.rengu.oltp.service.realize.impl.SmsServiceImpl;
import cc.rengu.oltp.utility.util.*;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 商户法人绑定认证.
 *
 * @author zhangxuran (联调修改)
 * @version 1.0
 * @date 2020.06.15
 */
public class MchntBindAuthService extends ManageService {

    @Override
    protected Object bizBeforeCust() throws Exception {
        MchntBindAuthRequest mchntBindAuthRequest = new MchntBindAuthRequest();
        ConvertUtil.convertOutput(mchntBindAuthRequest);
        return mchntBindAuthRequest;
    }

    @Override
    protected BizResponse bizProcessCust(Object request) throws Exception {

        MchntBindAuthRequest mchntBindAuthRequest = (MchntBindAuthRequest) request;
        MchntBindAuthResponse mchntBindAuthResponse = new MchntBindAuthResponse();
        String instId = mchntBindAuthRequest.getHeader().getInstId();
        String chanenelId = mchntBindAuthRequest.getHeader().getChanlId();
        String mchntNo = mchntBindAuthRequest.getMchntNo();
        String mchntType = mchntBindAuthRequest.getMchntType();
        String certType = mchntBindAuthRequest.getArtifCertType();
        String certNo = mchntBindAuthRequest.getArtifCertNo();
        String artifName = mchntBindAuthRequest.getArtifName();
        String sessionId = mchntBindAuthRequest.getHeader().getSession();
        rglog.info("必填性校验");
        if (StringUtil.isEmptyOrNull(instId) || StringUtil.isEmptyOrNull(mchntNo) || StringUtil.isEmptyOrNull(mchntType)
                || (!"00".equals(mchntType) && StringUtil.isEmptyOrNull(certType)) || (!"00".equals(mchntType) && StringUtil.isEmptyOrNull(certNo))
                || (!"00".equals(mchntType) && StringUtil.isEmptyOrNull(artifName))) {
            rglog.error("必填性校验失败！instId:<{}>,mchntNo:<{}>,mchntType:<{}>,certType:<{}>,certNo:<{}>,artifName:<{}>", instId, mchntNo, mchntType, certType, certNo, artifName);
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        /* 检查商户是否已注册 */
        String roleType;
        if (BspsMchntTypeEnum.AGENT_MCHNT.getMchntType().equals(mchntType)) {
            roleType = BspsUserRoleTypeEnum.AGENT_MANAGER.getRoleType();
        } else if (BspsMchntTypeEnum.PLAT_MCHNT.getMchntType().equals(mchntType)) {
            roleType = BspsUserRoleTypeEnum.PLATFORM_MANAGER.getRoleType();
        } else if (BspsMchntTypeEnum.GROUP_MCHNT.getMchntType().equals(mchntType)) {
            roleType = BspsUserRoleTypeEnum.GROUP_MANAGER.getRoleType();
        } else {
            BspsMchntBaseInfoMapper bspsMchntBaseInfoMapper = new BspsMchntBaseInfoMapperImpl();
            MchntBaseInfo mchntBaseInfo = bspsMchntBaseInfoMapper.selectBspsMchntBaseInfoByPrimaryKey(instId, mchntNo);
            if (null != mchntBaseInfo && MchntStatusEnum.NORMAL.getStatus().equals(mchntBaseInfo.getMchntStatus())) {
                mchntType = mchntBaseInfo.getMchntType();
            } else {
                rglog.error("商户状态异常");
                throw new BizException(RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespCode(), RespCodeEnum.MCHNT_STATUS_ABNORMAL.getRespDesc());
            }
            if (BspsMchntTypeEnum.CHAIN_MCHNT_STORE.getMchntType().equals(mchntType)) {
                roleType = BspsUserRoleTypeEnum.MCHNT_MANAGER.getRoleType();
            } else {
                roleType = BspsUserRoleTypeEnum.MCHNT_ARTIF.getRoleType();
            }
        }
        rglog.info("查询商户绑定信息");
        BspsMchntBindInfoMapper bspsMchntBindInfoMapper = new BspsMchntBindInfoMapperImpl();
        List<MchntBindInfo> mchntBindInfoList = bspsMchntBindInfoMapper.selectBspsMchntBindInfoByMchntNoAndRoleType(instId, mchntNo, roleType);
        if (!CollectionUtils.isEmpty(mchntBindInfoList)) {
            rglog.info("商户存在绑定用户,数量：" + mchntBindInfoList.size());
            if (BspsMchntTypeEnum.AGENT_MCHNT.getMchntType().equals(mchntType) || BspsMchntTypeEnum.PLAT_MCHNT.getMchntType().equals(mchntType)
                    || BspsMchntTypeEnum.GROUP_MCHNT.getMchntType().equals(mchntType)) {
                rglog.error("商户已注册");
                throw new BizException(RespCodeEnum.MCHNT_ALREADY_REGISTER.getRespCode(), RespCodeEnum.MCHNT_ALREADY_REGISTER.getRespDesc());
            }
            if (mchntBindInfoList.size() == 1) {
                MchntBindInfo mchntBindInfo = mchntBindInfoList.get(0);
                /*查询用户*/
                BspsUserInfoMapper bspsUserInfoMapper = new BspsUserInfoMapperImpl();
                UserInfo userInfo = bspsUserInfoMapper.selectBspsUserInfoByUserId(mchntBindInfo.getInstId(), mchntBindInfo.getBindUserId());
                if (userInfo == null) {
                    rglog.error("根据机构号：<{}>，商户号：<{}>查询商户绑定关系，存在商户法人信息!", instId, mchntNo);
                    throw new BizException(RespCodeEnum.MCHNT_ALREADY_REGISTER.getRespCode(), "商户已注册,注册用户信息异常");
                } else {
                    /*已经注册用户*/
                    String userLoginId = userInfo.getUserLoginId();
                    String openId = userInfo.getOpenId();
                    rglog.info("注册用户userLoginId:<{}>,注册用户openId:<{}>", userLoginId, openId);
                    if ("WECHAT".equals(chanenelId)) {
                        rglog.error("根据机构号：<{}>，商户号：<{}>查询商户绑定关系，存在法人或管理员信息!instId:<{}>,商户号:<{}>,openId:<{}>,渠道:<{}>", instId, mchntNo, openId, chanenelId);
                        throw new BizException(RespCodeEnum.MCHNT_ALREADY_REGISTER.getRespCode(), RespCodeEnum.MCHNT_ALREADY_REGISTER.getRespDesc());
                    }
                    if ("PCWEB".equals(chanenelId) && !StringUtil.isEmptyOrNull(userLoginId) && !"LOGINID".equals(userLoginId)) {
                        rglog.error("根据机构号：<{}>，商户号：<{}>查询商户绑定关系，存在商户法人信息!instId:<{}>,商户号:<{}>,登录账户:<{}>,渠道:<{}>", instId, mchntNo, userLoginId, chanenelId);
                        throw new BizException(RespCodeEnum.MCHNT_ALREADY_REGISTER.getRespCode(), RespCodeEnum.MCHNT_ALREADY_REGISTER.getRespDesc());
                    }
                }
            } else {
                rglog.error("根据机构号：<{}>，商户号：<{}>查询商户绑定关系，存在商户法人信息!", instId, mchntNo);
                throw new BizException(RespCodeEnum.MCHNT_ALREADY_REGISTER.getRespCode(), RespCodeEnum.MCHNT_ALREADY_REGISTER.getRespDesc());
            }
        }

        String mobileNo;
        rglog.info("查询商户信息");
        if (BspsMchntTypeEnum.AGENT_MCHNT.getMchntType().equals(mchntType)) {
            rglog.info("代理商获取代理商信息");
            BspsAgentInfoMapper bspsAgentInfoMapper = new BspsAgentInfoMapperImpl();
            AgentInfo agentInfo = bspsAgentInfoMapper.selectBspsAgentInfoByInstIdAndAgentCode(instId, mchntNo);
            if (null == agentInfo) {
                rglog.error("根据机构号:<{}>，商户号：<{}>查询代理商商户信息失败!", instId, mchntNo);
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            /* 校验商户法人信息 */
            verifyArtifInfo(agentInfo.getArtifCertType(), certType, agentInfo.getArtifCertNo(), certNo, agentInfo.getArtifName(), artifName);
            mobileNo = agentInfo.getArtifMobile();
        } else if (BspsMchntTypeEnum.PLAT_MCHNT.getMchntType().equals(mchntType)) {
            rglog.info("平台商户获取平台商户信息");
            BspsPlatformMchntInfoMapper bspsPlatformMchntInfoMapper = new BspsPlatformMchntInfoMapperImpl();
            PlatformMchntInfo platformMchntInfo = bspsPlatformMchntInfoMapper.selectBspsPlatformMchntInfoByInstIdAndMchntNo(instId, mchntNo);
            if (null == platformMchntInfo) {
                rglog.error("根据机构号:<{}>，商户号：<{}>查询平台商商户信息失败!", instId, mchntNo);
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            /* 校验商户法人信息 */
            verifyArtifInfo(platformMchntInfo.getArtifCertType(), certType, platformMchntInfo.getArtifCertNo(), certNo, platformMchntInfo.getArtifName(), artifName);
            mobileNo = platformMchntInfo.getArtifMobile();
        } else if (BspsMchntTypeEnum.GROUP_MCHNT.getMchntType().equals(mchntType)) {
            rglog.info("集团商户获取集团商户信息");
            MchntService mchntService = new MchntServiceImpl();
            GroupMchntInfo groupMchntInfo = mchntService.getGroupMchntInfo(instId, mchntNo);
            if (null == groupMchntInfo) {
                rglog.error("根据机构号:<{}>，商户号：<{}>查询集团商户信息失败!", instId, mchntNo);
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            /* 校验商户法人信息 */
            verifyArtifInfo(groupMchntInfo.getArtifCertType(), certType, groupMchntInfo.getArtifCertNo(), certNo, groupMchntInfo.getArtifName(), artifName);
            mobileNo = groupMchntInfo.getArtifMobile();
        } else {
            rglog.info("普通商户获取商户信息");
            BspsMchntSignInfoMapper bspsMchntSignInfoMapper = new BspsMchntSignInfoMapperImpl();
            MchntSignInfo mchntSignInfo = bspsMchntSignInfoMapper.selectBspsMchntSignInfoByPrimaryKey(instId, mchntNo);
            if (null == mchntSignInfo) {
                rglog.error("根据机构号:<{}>，商户号：<{}>查询普通商户签约信息失败!", instId, mchntNo);
                throw new BizException(RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespCode(), RespCodeEnum.MCHNT_INFO_NOT_FOUND.getRespDesc());
            }
            mobileNo = mchntSignInfo.getArtifMobile();
        }
        rglog.info("法人手机号:<{}>", mobileNo);
        /* 生成短信验证码 */
        /* 获取短信模板枚举类型 */
        TemplateTypeEnum templateTypeEnum = SmsTypeEnum.getTemplateTypeEnum("02");
        if (null == templateTypeEnum) {
            rglog.error("不支持的验证码类型!");
            throw new BizException(RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespCode(), RespCodeEnum.MSG_VALID_CHECK_ERROR.getRespDesc());
        }
        /* 获取短信模板 */
        MsgTemplateCfgMapper msgTemplateCfgMapper = new MsgTemplateCfgMapperImpl();
        MsgTemplateCfg msgTemplateCfg = msgTemplateCfgMapper.selectMsgTemplateCfgByTemplateType(instId, templateTypeEnum.getTemplateType());
        if (null == msgTemplateCfg) {
            msgTemplateCfg = msgTemplateCfgMapper.selectMsgTemplateCfgByTemplateType(AppParamConstant.DEFAULT_INSTID, templateTypeEnum.getTemplateType());
            if (null == msgTemplateCfg) {
                rglog.error("未配置短信发送模板!");
                throw new BizException(RespCodeEnum.NOT_CONF_MSG_TEMPLATE.getRespCode(), RespCodeEnum.NOT_CONF_MSG_TEMPLATE.getRespDesc());
            }
        }
        rglog.debug("短信模板代码:<{}>,短信模板内容:<{}>", msgTemplateCfg.getTemplateCode(), msgTemplateCfg.getTemplateDesc());
        SmsService smsService = new SmsServiceImpl();
        SmsInfo smsInfo = smsService.generateSmsCode(instId, mobileNo, "02");
        if (null == smsInfo) {
            rglog.error("生成短信验证码失败!");
            throw new BizException(RespCodeEnum.GEN_SMS_CODE_ERROR.getRespCode(), RespCodeEnum.GEN_SMS_CODE_ERROR.getRespDesc());
        } else {
            mchntBindAuthResponse.setSmsAuthId(smsInfo.getVerifySeqNum());
        }
        String smsContent = parseSmsTemplateInfo(msgTemplateCfg.getTemplateDesc(), smsInfo.getSmsCode());
        /* 调用支付通道发送短信 */
        /* 获取通道交易码 */
        Optional<ChannelCallCfg> channelCallCfgOpt = txnInfo.getChannelCallCfgList().stream().filter(item -> item.getCallChannelId().equals(ChannelEnum.ESB.getChannelType())).findFirst();
        if (!channelCallCfgOpt.isPresent()) {
            rglog.error("未配置通道的通道服务调用配置,txnKey:<{}>,msgDstId:<{}>", txnInfo.getTxnKey(), ChannelEnum.ESB.getChannelType());
            throw new BizException(RespCodeEnum.NOT_CONF_CHANNEL_TXN_MAP.getRespCode(), RespCodeEnum.NOT_CONF_CHANNEL_TXN_MAP.getRespDesc());
        }
        DubboService dubboService = new DubboServiceImpl();
        Header header = new Header();
        header.setVersion("1.0.0");
        header.setTransDate(DateUtil.getCurrentDate());
        header.setTransTime(DateUtil.getCurrentTime());
        header.setTxnNum(channelCallCfgOpt.get().getCallChannelTxn());
        header.setBizType(AppParamConstant.DEFAULT_BIZ_TYPE);
        header.setInstId(instId);
        header.setSrcSysId(AppParamConstant.IGAS);
        header.setChanlId(ChannelEnum.BSPS.getChannelType());
        header.setTraceNo(GlobalEsbUtil.generateEsbSeqeuenceNumber(instId));
        GeneralSmsNoticeRequest generalSMSNoticeRequest = new GeneralSmsNoticeRequest();
        generalSMSNoticeRequest.setHeader(header);
        generalSMSNoticeRequest.setRealtimeFlag(AppParamConstant.YES);
        List<String> phoneNoList = new ArrayList<>();
        phoneNoList.add(mobileNo);
        generalSMSNoticeRequest.setPhoneList(phoneNoList);
        generalSMSNoticeRequest.setTemplateId(msgTemplateCfg.getTemplateCode());
        generalSMSNoticeRequest.setSmsContent(smsContent);
        Result<GeneralSmsNoticeResponse> result = (Result<GeneralSmsNoticeResponse>) dubboService.callDubboService(DubboMethodConstant.SMS_SEND_SERVICE, DubboMethodConstant.SMS_MSG_PUSH, generalSMSNoticeRequest);
        if (null == result || !result.isSuccess() || null == result.getResult()) {
            throw new BizException(RespCodeEnum.GEN_SMS_CODE_ERROR.getRespCode(), RespCodeEnum.GEN_SMS_CODE_ERROR.getRespDesc());
        }

        //短信验证码存入redis缓存
        String userSessionString;
        if (StringUtil.isEmptyOrNull(sessionId) || StringUtil.isEmptyOrNull(userSessionString = RedisUtil.onceGet(sessionId))) {
            rglog.error("用户未登录或者Session已过期!");
            throw new BizException(RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespCode(), RespCodeEnum.USER_NOT_LOGIN_OR_SESSION_IS_EXPIRED.getRespDesc());
        }
        UserSessionInfo userSessionInfo = JSON.parseObject(userSessionString, UserSessionInfo.class);
        userSessionInfo.setSmsVerifySeqNum(smsInfo.getVerifySeqNum());
        RedisUtil.onceSet(sessionId, JSONObject.toJSONString(userSessionInfo), BspsAppParamConstant.SESSION_EFFECTIVE_TIME);

        /* 拼装响应结果 */
        BizResponse<MchntBindAuthResponse> bizResponse = new BizResponse<>();
        if (!StringUtil.isEmptyOrNull(mobileNo)) {
            mobileNo = SensitiveDataUtil.desensitization("1", mobileNo).split("\\|")[0];
        }
        mchntBindAuthResponse.setArtifMobile(mobileNo);
        mchntBindAuthResponse.setSmsAuthId(smsInfo.getVerifySeqNum());
        bizResponse.setRspSysId(AppParamConstant.SYS_ID);
        bizResponse.setRespCode(RespCodeEnum.TRANS_SUCCESS.getRespCode());
        bizResponse.setRespDesc(RespCodeEnum.TRANS_SUCCESS.getRespDesc());
        bizResponse.setResult(mchntBindAuthResponse);
        return bizResponse;
    }

    @Override
    protected void bizAfterCust(Object response) throws Exception {
        BizResponse bizResponse = (BizResponse) response;
        MchntBindAuthResponse mchntBindAuthResponse = (MchntBindAuthResponse) bizResponse.getResult();
        ConvertUtil.convertInput(mchntBindAuthResponse);
    }

    /**
     * 校验法人信息
     */
    private void verifyArtifInfo(String artifCertType, String requestCerType,
                                 String artifCertNo, String requestCertNo,
                                 String artifName, String requestName) {


        if (StringUtil.isEmptyOrNull(artifCertType) || !artifCertType.equals(requestCerType)) {
            rglog.error("用户输入证件类型<{}>与商户签约信息证件类型<{}>不一致!", requestCerType, artifCertType);
            throw new BizException(RespCodeEnum.USER_BIND_MCHNT_ERROR.getRespCode(), RespCodeEnum.USER_BIND_MCHNT_ERROR.getRespDesc());
        }

        if (StringUtil.isEmptyOrNull(artifCertNo) || !artifCertNo.equals(requestCertNo)) {
            rglog.error("用户输入证件号码<{}>与商户签约信息证件号码<{}>不一致!", requestCertNo, artifCertNo);
            throw new BizException(RespCodeEnum.USER_BIND_MCHNT_ERROR.getRespCode(), RespCodeEnum.USER_BIND_MCHNT_ERROR.getRespDesc());

        }

        if (StringUtil.isEmptyOrNull(artifName) || !artifName.equals(requestName)) {
            rglog.error("输入姓名<{}>与商户签约商户法人<{}>不一致!", requestName, artifName);
            throw new BizException(RespCodeEnum.USER_BIND_MCHNT_ERROR.getRespCode(), RespCodeEnum.USER_BIND_MCHNT_ERROR.getRespDesc());
        }
    }

    /**
     * 动态解析短信模板生成短信内容
     *
     * @param templateDesc 短信模板内容
     * @param smsCode      短信验证码
     * @return 短信内容
     * @throws Exception 异常
     */
    private String parseSmsTemplateInfo(String templateDesc, String smsCode) throws Exception {
        XmlTreeUtil xmlTreeUtil = new XmlTreeUtil();
        StringBuilder stringBuilder = new StringBuilder();
        while (!StringUtil.isEmptyOrNull(templateDesc) && templateDesc.contains("[")) {
            int startIndex = templateDesc.indexOf('[');
            stringBuilder.append(templateDesc, 0, startIndex);
            templateDesc = templateDesc.substring(startIndex + 1);
            int endIndex = templateDesc.indexOf(']');
            String key = templateDesc.substring(0, endIndex);
            if ("smsCode".equals(key)) {
                stringBuilder.append(smsCode);
            } else {
                String value = xmlTreeUtil.getXmlTreeStringValue(key.trim());
                if (null == value) {
                    rglog.error("根据动态模板获取字段值失败,key:<{}>", key);
                    throw new BizException(RespCodeEnum.SEND_SMS_CODE_ERROR.getRespCode(), RespCodeEnum.SEND_SMS_CODE_ERROR.getRespDesc());
                } else {
                    stringBuilder.append(value);
                }
            }
            templateDesc = templateDesc.substring(endIndex + 1);
        }
        stringBuilder.append(templateDesc);
        return stringBuilder.toString();
    }

}
